package io.netopen.hotbitmapgg.library;


import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.agp.utils.TextTool;
import ohos.app.Context;

/**
 * Created by hcc on 16/7/13 19:54
 * 100332338@qq.com
 * <p/>
 * 一个自定义的圆环进度条
 * 可适用于上传下载
 *
 * @since 2021/07/01
 */
public class RingProgressBar extends Component implements Component.DrawTask, Component.EstimateSizeListener {
    /**
     * 空心样式
     */
    public static final int STROKE = 0;

    /**
     * 实心样式
     */
    public static final int FILL = 1;

    // 画笔对象
    private final Paint paint;

    // View宽度
    private int width;

    // 默认宽高值
    private final int result;

    // 默认padding值
    private final float padding;

    // 圆环的颜色
    private int ringColor;

    // 圆环进度颜色
    private int ringProgressColor;

    // 文字颜色
    private int textColor;

    // 文字大小
    private float textSize;

    // 圆环宽度
    private float ringWidth;

    // 最大值
    private int max;

    // 进度值
    private int progress;

    // 是否显示文字
    private final boolean textIsShow;

    // 圆环进度条的样式
    private final int style;

    // 进度回调接口
    private OnProgressListener mOnProgressListener;

    // 圆环中心
    private int centre;

    // 圆环半径
    private int radius;

    public RingProgressBar(Context context) {
        this(context, null);
    }

    public RingProgressBar(Context context, AttrSet attrs) {
        this(context, attrs, 0);
    }

    public RingProgressBar(Context context, AttrSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // 初始化画笔
        paint = new Paint();
        // 初始化默认宽高值
        result = dp2px(100);
        // 初始化属性
        ringColor = AttrUtils.getColorFromAttr(attrs, "ringColor", Color.BLACK.getValue());
        ringProgressColor = AttrUtils.getColorFromAttr(attrs, "ringProgressColor",
                Color.WHITE.getValue());
        textColor = AttrUtils.getColorFromAttr(attrs, "textColor", Color.BLACK.getValue());
        textSize = AttrUtils.getDimensionFromAttr(attrs, "textSize", 16);
        ringWidth = AttrUtils.getDimensionFromAttr(attrs, "ringWidth", 5);
        max = AttrUtils.getIntegerFromAttr(attrs, "max", 100);
        textIsShow = AttrUtils.getBooleanFromAttr(attrs, "textIsShow", true);
        style = getStyle(AttrUtils.getStringFromAttr(attrs, "style", "STROKE"));
        progress = AttrUtils.getIntegerFromAttr(attrs, "progress", 0);
        padding = AttrUtils.getDimensionFromAttr(attrs, "ringPadding", 5);
        addDrawTask(this);
        setEstimateSizeListener(this);
    }

    /**
     * 设置样式
     *
     * @param type style
     * @return int
     */
    private int getStyle(String type) {
        int reType = STROKE;
        if (TextTool.isEqual(type, "FILL")) {
            reType = FILL;
        }
        return reType;
    }

    /**
     * onDraw
     *
     * @param component component
     * @param canvas canvas
     */
    @Override
    public void onDraw(Component component, Canvas canvas) {
        centre = width / 2;
        radius = (int) (centre - ringWidth / 2);
        //绘制外层圆
        drawCircle(canvas);
        //绘制文本内容
        drawTextContent(canvas);
        //绘制进度条
        drawProgress(canvas);
    }

    /**
     * 绘制外层圆环
     *
     * @param canvas canvas
     */
    private void drawCircle(Canvas canvas) {
        // 设置画笔颜色
        paint.setColor(new Color(ringColor));
        // 设置画笔样式
        paint.setStyle(Paint.Style.STROKE_STYLE);
        // 设置stroke的宽度
        paint.setStrokeWidth(ringWidth);
        // 设置抗锯齿
        paint.setAntiAlias(true);
        // 绘制圆形
        canvas.drawCircle(centre, centre, radius, paint);
    }

    /**
     * 绘制进度文本
     *
     * @param canvas canvas
     */
    private void drawTextContent(Canvas canvas) {
        // 设置stroke的宽度
        paint.setStyle(Paint.Style.FILL_STYLE);
        paint.setStrokeWidth(1);
        // 设置文字的颜色
        paint.setColor(new Color(textColor));
        // 设置文字的大小
        paint.setTextSize((int) textSize);
        // 设置文字的style
        paint.setFont(Font.DEFAULT);
        // 设置进度值
        int percent = (int) (((float) progress / (float) max) * 100);
        // 获取文字的宽度 用于绘制文本内容
        float textWidth = paint.measureText(percent + "%");
        // 绘制文本 会根据设置的是否显示文本的属性&是否是Stroke的样式进行判断
        if (textIsShow && percent != 0 && style == STROKE) {
            canvas.drawText(paint, percent + "%", centre - textWidth / 2, centre + textSize / 2);
        }
    }

    /**
     * 绘制进度条
     *
     * @param canvas canvas
     */
    private void drawProgress(Canvas canvas) {
        // 绘制进度 根据设置的样式进行绘制
        paint.setStrokeWidth(ringWidth);
        paint.setColor(new Color(ringProgressColor));
        // Stroke样式
        RectFloat strokeOval = new RectFloat(centre - radius, centre - radius, centre + radius,
                centre + radius);
        // FIll样式
        RectFloat fillOval = new RectFloat(centre - radius + ringWidth + padding,
                centre - radius + ringWidth + padding, centre + radius - ringWidth - padding,
                centre + radius - ringWidth - padding);
        switch (style) {
            case STROKE: {
                paint.setStyle(Paint.Style.STROKE_STYLE);
                paint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
                Arc arc = new Arc();
                arc.setArc(-90, 360 * progress / max, false);
                canvas.drawArc(strokeOval, arc, paint);
                break;
            }
            case FILL: {
                paint.setStyle(Paint.Style.FILLANDSTROKE_STYLE);
                paint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
                if (progress != 0) {
                    Arc arc = new Arc();
                    arc.setArc(-90, 360 * progress / max, true);
                    canvas.drawArc(fillOval, arc, paint);
                }
                break;
            }
        }
    }

    /**
     * onEstimateSize
     *
     * @param widthMeasureSpec  widthMeasureSpec
     * @param heightMeasureSpec heightMeasureSpec
     * @return boolean
     */
    @Override
    public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
        // 获取宽高的mode和size
        int widthMode = EstimateSpec.getMode(widthMeasureSpec);
        int widthSize = EstimateSpec.getSize(widthMeasureSpec);
        int heightMode = EstimateSpec.getMode(heightMeasureSpec);
        int heightSize = EstimateSpec.getSize(heightMeasureSpec);
        // 测量宽度
        if (widthMode == EstimateSpec.NOT_EXCEED) {
            width = result;
        } else {
            width = widthSize;
        }
        // 测量高度
        // View高度
        int height;
        if (heightMode == EstimateSpec.NOT_EXCEED) {
            height = result;
        } else {
            height = heightSize;
        }
        // 设置测量的宽高值
        setEstimatedSize(
                Component.EstimateSpec.getChildSizeWithMode(width, width, Component.EstimateSpec.NOT_EXCEED),
                Component.EstimateSpec.getChildSizeWithMode(height, height, Component.EstimateSpec.NOT_EXCEED));
        return true;
    }

    /**
     * 获取当前的最大进度值
     *
     * @return int
     */
    public synchronized int getMax() {
        return max;
    }

    /**
     * 设置最大进度值
     *
     * @param max max
     * @throws IllegalArgumentException illegalArgumentException
     */
    public synchronized void setMax(int max) {
        if (max < 0) {
            throw new IllegalArgumentException("The max progress of 0");
        }
        this.max = max;
    }

    /**
     * 获取进度值
     *
     * @return int
     */
    public synchronized int getProgress() {
        return progress;
    }

    /**
     * 设置进度值 根据进度值进行View的重绘刷新进度
     *
     * @param progress progress
     * @throws IllegalArgumentException IllegalArgumentException
     */
    public void setProgress(int progress) {
        int tempProgress = progress;
        if (progress < 0) {
            throw new IllegalArgumentException("The progress of 0");
        }
        if (progress > max) {
            tempProgress = max;
        }
        if (progress <= max) {
            this.progress = tempProgress;
            invalidate();
        }
        if (progress == max) {
            if (mOnProgressListener != null) {
                mOnProgressListener.progressToComplete();
            }
        }
    }

    /**
     * 获取圆环的颜色
     *
     * @return int
     */
    public int getRingColor() {
        return ringColor;
    }

    /**
     * 设置圆环的颜色
     *
     * @param ringColor ringColor
     */
    public void setRingColor(int ringColor) {
        this.ringColor = ringColor;
    }

    /**
     * 获取圆环进度的颜色
     *
     * @return int
     */
    public int getRingProgressColor() {
        return ringProgressColor;
    }

    /**
     * 设置圆环进度的颜色
     *
     * @param ringProgressColor ringProgressColor
     */
    public void setRingProgressColor(int ringProgressColor) {
        this.ringProgressColor = ringProgressColor;
    }

    /**
     * 获取文字的颜色
     *
     * @return int
     */
    public int getTextColor() {
        return textColor;
    }

    /**
     * 设置文字颜色
     *
     * @param textColor textColor
     */
    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }

    /**
     * 获取文字的大小
     *
     * @return textSize textSize
     */
    public float getTextSize() {
        return textSize;
    }

    /**
     * 设置文字的大小
     *
     * @param textSize textSize
     */
    public void setTextSize(float textSize) {
        this.textSize = textSize;
    }

    /**
     * 获取圆环的宽度
     *
     * @return float
     */
    public float getRingWidth() {
        return ringWidth;
    }

    /**
     * 设置圆环的宽度
     *
     * @param ringWidth ringWidth
     */
    public void setRingWidth(float ringWidth) {
        this.ringWidth = ringWidth;
    }

    /**
     * vp转px
     *
     * @param vp vp
     * @return int
     */
    public int dp2px(int vp) {
        return AttrHelper.fp2px(vp, getContext());
    }

    /**
     * 进度完成回调接口
     */
    public interface OnProgressListener {
        void progressToComplete();
    }

    /**
     * mOnProgressListener
     *
     * @param mOnProgressListener mOnProgressListener
     */
    public void setOnProgressListener(OnProgressListener mOnProgressListener) {
        this.mOnProgressListener = mOnProgressListener;
    }
}
